package com.example.demo.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;

/**
 * @Title: GulimailSessionConfig
 * @Author 纪圣辉
 * @Package com.jsh.gulimail.auth.config
 * @Date 2025/8/19 下午7:29
 * @description: Session配置
 */
@Configuration
public class SessionConfig {

    /**
     * Cookie序列化配置
     * <p>
     * - `cookieName`：要使用的 cookie 名称。默认值：`SESSION`。
     * - `useSecureCookie`：指定是否应使用安全 cookie。默认值：创建时使用 `HttpServletRequest.isSecure()` 的值。
     * - `cookiePath`：cookie 的路径。默认值：上下文根路径。
     * - `cookieMaxAge`：指定在创建 session 时设置的 cookie 的最大生存期。默认值：`-1`，表示在浏览器关闭时应移除 cookie。
     * - `jvmRoute`：指定要附加到 session ID 并包含在 cookie 中的后缀。用于识别要路由到哪个 JVM 以实现 session 亲和性。对于某些实现（例如 Redis），此选项不提供性能优势。但是，它可以帮助追踪特定用户的日志。
     * - `domainName`：允许指定用于 cookie 的特定域名。此选项易于理解，但通常需要在开发和生产环境之间进行不同的配置。请参阅 `domainNamePattern` 作为替代方案。
     * - `domainNamePattern`：一个不区分大小写的模式，用于从 `HttpServletRequest#getServerName()` 中提取域名。该模式应提供一个单独的分组，用于提取 cookie 域的值。如果正则表达式不匹配，则不设置 domain，并使用现有 domain。如果正则表达式匹配，则第一个[分组](https://docs.oracle.com/javase/tutorial/essential/regex/groups.html)将用作 domain。
     * - `sameSite`：`SameSite` cookie 指令的值。要禁用 `SameSite` cookie 指令的序列化，您可以将此值设置为 `null`。默认值：`Lax`
     *
     * @return CookieSerializer
     */
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieMaxAge(60 * 60 * 24 * 30);
        serializer.setCookieName("user"); // 使用标准的JSESSIONID名称
        // 设置cookie路径为根路径
        serializer.setCookiePath("/");
        // 在开发环境中，将SameSite设置为None以允许跨站点Cookie设置
        serializer.setSameSite("Lax");
        // 在开发环境中，即使SameSite=None也设置useSecureCookie=false以适应HTTP环境
        serializer.setUseSecureCookie(false);
        // 重要：在开发环境中不设置域名，允许在任何域名下使用Cookie
        return serializer;
    }

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        // 创建ObjectMapper并注册JavaTimeModule以支持LocalDateTime等时间类型
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        // 启用类型信息存储，以便反序列化时能正确还原对象类型
        objectMapper.activateDefaultTyping(
                objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL);
        // 添加类型信息到JSON中
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }

}